#include "tile/tilemaploader.hpp"

#include "tile/emptytile.hpp"
#include "tile/tilemap.hpp"
#include "tile/slopinglefttile.hpp"
#include "tile/slopingrighttile.hpp"
#include "tile/solidtile.hpp"
#include "util/fileutil.hpp"
#include "util/stringutil.hpp"

#include "game.hpp"

#include <vector>

namespace nmc
{
	TileMap* TileMapLoader::getTileMap(const std::string& filename)
	{
		int width = 0;
		int height = 0;

		std::vector<std::string> data = tokenize(loadFile(filename), "\n");
		
		
		
		if (data.size() == 0)
		{
			throw NMC_EXCEPTION("Tile map is empty!");
		}

		width = data[0].size();
		height = data.size();
		

		TileMap* tileMap = new TileMap(width, height);

		for (unsigned int row = 0; row < data.size(); row++)
		{
			Game::instance()->log(data[row]);
			
			if (data[row].size() != width)
			{
				throw NMC_EXCEPTION("Tile map is corrupt, line " + toString(row) + ". The line is either too long or too small.");
			}

			for (unsigned int col = 0; col < data[row].size(); col++)
			{
				Point tileMapPosition(col, row);
				switch (data[row].at(col))
				{	
					case '1':
					{
						Tile* tile = new SolidTile(tileMapPosition, tileMap);
						tileMap->setTile(tile, col, row);
						break;
					}
					case '2':
					{
						Tile* tile = new SlopingRightTile(tileMapPosition, tileMap);
						tileMap->setTile(tile, col, row);
						break;
					}
					case '3':
					{
						Tile* tile = new SlopingLeftTile(tileMapPosition, tileMap);
						tileMap->setTile(tile, col, row);
						break;

					}
					case '.':
					{
						Tile* tile = new EmptyTile(tileMapPosition, tileMap);
						tileMap->setTile(tile, col, row);
						break;
					}
					default:
						throw NMC_EXCEPTION("Unknown tile type! " + toString(data[row].at(col)));
				}
			}
		}

		tileMap->calculateSolidities();

		return tileMap;
	}
}